<?php
declare (strict_types = 1);

namespace app\command;

use app\admin\controller\Qbapi;
use app\admin\controller\Trapi;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use Rhilip\Bencode\Bencode;
use think\admin\model\SystemDownload;
use think\admin\model\SystemSites;
use think\admin\model\SystemQueueLog;
use think\console\Input;
use think\console\Output;
use think\facade\Cache;

class Cron extends \think\admin\Command

{
    protected function configure()
    {
        // 指令配置
        $this->setName('cron')
            ->setDescription('辅种计划任务');
    }

    protected function execute(Input $input, Output $output)
    {
        // 获取所有参与辅种的下载器ID
        $downloadIds = $this->queue->data;
        foreach ($downloadIds as $downloadId) {
          // 查询当前下载器ID的数据库信息
          $downloadResult = SystemDownload::mQuery()->db()->where('id', $downloadId)->find();
          $msg = '正在执行'.$downloadResult['name'].'下载器的辅种任务';
          $this->msg($msg);
          $this->setQueueProgress($msg, '10');
          // 查询当前下载器配置的参与辅种的站点信息
          $siteResult = SystemSites::mQuery()->db()->whereIn('id', array_map('intval', explode(',', $downloadResult['reseed_sites'])))->select();
          // 判断当前是否找到下载器信息
          if ($downloadResult) {
            $msg = '正在检索种子库';
            $this->msg($msg);
            $this->setQueueProgress($msg, '10');
            foreach (scandir($downloadResult['save_path']) as $file_name) {
                if (pathinfo($file_name, PATHINFO_EXTENSION) == 'torrent') {
                    $file_path = $downloadResult['save_path'] . '/' . $file_name;
                    try {
                        $torrent_data = file_get_contents($file_path);
                        $torrent = Bencode::decode($torrent_data);
                        $info = $torrent['info'];
                        $pieces = $info['pieces'];
                        $info_sha1 = sha1(Bencode::encode($info));
                        $pieces_sha1 = sha1($pieces);
                        $pieces_hash_list[] = $pieces_sha1;
                        $info_hash_topieces[$pieces_sha1] = $info_sha1;
                        $torrent_name_topieces[$pieces_sha1] = $file_name;
                    } catch (\Exception $e) {
                        continue;
                    }
                }
            }
            $cached_pieces_hash_list = Cache::get('pieces_hash_list') ?? [];
            $pieces_hash_list = array_diff($pieces_hash_list, $cached_pieces_hash_list);
            $msg = '目录中检索到种子数：' . count($pieces_hash_list) . '|缓存中种子数：' . count($cached_pieces_hash_list).'|参与辅种种子数：' . count($pieces_hash_list);
            $this->msg($msg);
            $this->setQueueProgress($msg, '60');

            $fz_array = [];
            if ( count($siteResult) == 0) {
                $msg = '辅种列表为空，请点击头像清理缓存或检查映射目录是否正确';
                $this->msg($msg);
                $this->setQueueProgress($msg, '100');
                continue;
            }
            foreach ($siteResult as $site) {
                if (isset($site['passkey']) && $site['passkey'] != '') {
                    $msg = '正在请求' . $site['site_name'] . "站点";
                    $this->msg($msg);
                    $this->setQueueProgress($msg, '70');
                    $pieces_hash_groups = array_chunk($pieces_hash_list, 100);
                    foreach ($pieces_hash_groups as $group_list) {
                        $data = array(
                            'passkey' => $site['passkey'],
                            'pieces_hash' => $group_list,
                        );
                        $url = $site['api_url'];
                        try {
                            $response_json = $this->guzzlePost($url, $data);
                        } catch (\Exception $e) {
                            // $this->setQueueProgress('遇到错误:'.$e,'50');
                            continue;
                        }
                        if ($downloadResult['type'] == 1) {
                            $qbapi = new Qbapi($downloadResult);
                            if (is_array($response_json)) {
                                foreach ($response_json['data'] as $key => $value) {
                                    if ($value == 'passkey' || $value == 'pieces_hash') {
                                        continue;
                                    }
                                    $torrent_info = $qbapi->getTorrentsInfo($info_hash_topieces[$key], 'completed');
                                    if (!empty($torrent_info)) {
                                        $save_path = $torrent_info[0]['save_path'];
                                        $msg = '保存目录：' . $save_path ."下载站点：". $site['site_url'];
                                        $this->msg($msg);
                                        $this->setQueueProgress($msg, '70');
                                        sleep(2);
                                        if ($qbapi->addTorrent(
                                            $site['site_url'] . '/download.php?id=' . $value . '&passkey=' . $site['passkey'],
                                            $save_path,
                                            $downloadResult['is_skip_hash'],
                                            $downloadResult['is_paused'],
                                            $site['download_limit'],
                                            $site['upload_limit']) == 'Ok.') {
                                            array_push($cached_pieces_hash_list, $key);
                                            Cache::set('pieces_hash_list', $cached_pieces_hash_list);
                                            $fz_array[] = $site['site_url'] . '/download.php?id=' . $value . '&passkey=' . $site['passkey'];
                                            // 定义文件路径
                                            $filePath = 'public/torrent.json';
                                            // 如果文件不存在，则创建一个
                                            if (!file_exists($filePath)) {
                                                touch($filePath);
                                            }
                                            // 将数组转换为JSON格式
                                            $jsonData = json_encode($fz_array);
                                            // 写入数组到文件
                                            file_put_contents($filePath, $jsonData);
                                        }
                                    }
                                }
                            }
                        } else {
                            $trapi = new Trapi($downloadResult);
                            if (is_array($response_json)) {
                                foreach ($response_json['data'] as $key => $value) {
                                    if ($value == 'passkey' || $value == 'pieces_hash') {
                                        continue;
                                    }
                                    $torrent_info = $trapi->getTorrentsInfo($info_hash_topieces[$key]);
                                    if (!empty($torrent_info)) {
                                        $save_path = $torrent_info['arguments']['torrents'][0]['downloadDir'];
                                        $msg = '保存目录：' . $save_path ."下载站点：". $site['site_url'];
                                        $this->msg($msg);
                                        $this->setQueueProgress($msg, '70');
                                        sleep(2);
                                        $result = $trapi->addTorrent(
                                            $site['site_url'] . '/download.php?id=' . $value . '&passkey=' . $site['passkey'],
                                            $save_path,
                                            $downloadResult['is_paused']);
                                        if ($result['result'] == 'success') {
                                            array_push($cached_pieces_hash_list, $key);
                                            Cache::set('pieces_hash_list', $cached_pieces_hash_list);
                                            $fz_array[] = $site['site_url'] . '/download.php?id=' . $value . '&passkey=' . $site['passkey'];
                                            // 定义文件路径
                                            $filePath = 'public/torrent.json';
                                            // 如果文件不存在，则创建一个
                                            if (!file_exists($filePath)) {
                                                touch($filePath);
                                            }
                                            // 将数组转换为JSON格式
                                            $jsonData = json_encode($fz_array);
                                            // 写入数组到文件
                                            file_put_contents($filePath, $jsonData);
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else {
                    $msg = $site['site_name'] . '未配置passkey，跳过辅种';
                    $this->msg($msg);
                    $this->setQueueProgress($msg, '70');
                }
            }
            $msg = '成功辅种:' . count($fz_array) . '个种子';
            $this->msg($msg);
            $this->setQueueProgress($msg , '100');
          } else {
            $msg = "下载器ID不存在！请检查是否删除了对应下载器！";
            $this->msg($msg);
            $this->setQueueProgress($msg, '100');
          }
        }
        $this->setQueueSuccess('任务执行完成');
    }

    /**
     * 封装的一个通用guzzle请求
     */
    public function guzzlePost($url, $data)
    {
        $client = new Client();
        $parsedUrl = parse_url($url);
        $host = $parsedUrl['host'];
        $headers = array(
            'Content-Type: application/json',
            'Accept: */*',
            'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
            'Referer:' . $url,
            'Host:' . $host,
        );
        try {
            $response = $client->request("POST", $url, [
                'headers' => $headers,
                'json' => $data,
                'timeout' => 4,
                'verify' => false,
            ]);
        } catch (ClientException $e) {
            $msg = '站点访问失败，链接:' . $url;
            $this->msg($msg);
            $this->setQueueProgress($msg, '70');

        } catch (\ConnectException $e) {
            $msg = '站点访问超过4秒，链接:' . $url;
            $this->msg($msg);
            $this->setQueueProgress($msg, '70');
            return "失败";
        }

        $response_json = json_decode((string) $response->getBody(), true);
        $response->getBody()->close();
        return $response_json;
    }

    public function msg($message){
      // SystemQueueLog::mQuery()->db()->data(['msg'=>$message])->insert();
    }
}
